/*
 * GbtProxyAgent.h
 *
 *  Created on: 2018年5月16日
 *      Author: zhengboyuan
 */

#ifndef GBTPROXY_AGENT_H_
#define GBTPROXY_AGENT_H_

#include "GbtMediaDevice.h"

namespace gbt
{

/**
 * 消息处理器
 */
class GbtProxyMessageHandler
{
public:
    virtual ~GbtProxyMessageHandler() {}

    /// 无应答命令.

    /**
     * 控制云台/调用预置位
     * @param deviceID
     * @param cmd
     */
    virtual void handlePtzCommand(int id, const char* deviceID, const GBT_PtzCommand& cmd) =0;

    /**
     * 远程启动
     * @param deviceID
     * @param boot
     */
    virtual void handleTeleBoot(int id, const char* deviceID, GBT_TeleBoot& boot) =0;

    /**
     * 强制输出关键帧
     * @param deviceID
     */
    virtual void handleForceKeyFrame(int id, const char* deviceID) =0;

    /**
     * 缩放
     * @param deviceID
     * @param zoomMode  放大/缩小 @see GBT_DragZoomMode
     * @param dragZoom
     */
    virtual void handleZoom(int id, const char* deviceID, GBT_DragZoomMode zoomMode, const GBT_DragZoom& dragZoom) =0;


    /// 有应答命令.

    /// 启停录像
    virtual bool handleRecordCmd(int id, const GBT_Command& req, const GBT_RecordCmd& cmd) =0;

    /**
     * 布防撤防
     */
    virtual bool handleGuardCmd(int id, const GBT_Command& req, const GBT_GuardCmd& cmd) =0;

    /**
     * 报警复位
     */
    virtual bool handleAlarmCmd(int id, const GBT_Command& req, const GBT_AlarmCmd& cmd) =0;

    /**
     * 设置看守位
     */
    virtual bool handleSetHomePosition(int id, const GBT_Command& req, const GBT_HomePosition& cmd) =0;

    /**
     * 配置设备
     * @param config
     * @return
     */
    virtual bool handleDeviceConfig(int id, const GBT_Command& req, const GBT_DeviceConfig& config) =0;


    /**
     * 查理查询设备信息
     * @param id	设备序号
     * @param req	查询命令
     * @param info	待返回的设备信息
     * @return true 表示找到设备信息
     */
    virtual bool handleQueryDeviceInfo(int id, const GBT_Command& req, GBT_DeviceInfo& info) =0;

    /**
     * 处理查询设备状态
     * @param id
     * @param req
     * @param status	待返回的设备状态信息
     * @return true 表示找到设备信息
     */
    virtual bool handleQueryDeviceStatus(int id, const GBT_Command& req, GBT_DeviceStatus& status) =0;

    virtual bool handleQueryBasicParam(int id, const GBT_Command& req, GBT_BasicParam& config) =0;
    virtual bool handleQueryVideoParamOpt(int id, const GBT_Command& req, GBT_VideoParamOpt& config) = 0;
    virtual bool handleQueryVideoParamConfig(int id, const GBT_Command& req, GBT_VideoParamConfig& config) = 0;
    virtual bool handleQueryAudioParamOpt(int id, const GBT_Command& req, GBT_AudioParamOpt& config) = 0;
    virtual bool handleQueryAudioParamConfig(int id, const GBT_Command& req, GBT_AudioParamConfig& config) = 0;
        
    /**
     * 处理查询录像
     * @param id	设备序号
     * @param req	查询命令
     * @param query	录像查询条件
     * @param records	查询结果
     * @param size		数组最大长度
     * @return	查询到的录像个数
     */
    virtual int handleQueryRecordInfo(int id, const GBT_Command& req, const GBT_RecordInfoQuery& query, GBT_RecordInfo* records, int size) =0;

    /**
     * 处理查询录像
     * @param id	设备序号
     * @param req	查询命令
     * @param query	查询条件
     * @param alarms	查询结果数组
     * @param size		数组最大长度
     * @return	查询到的个数
     */
    virtual int handleQueryAlarm(int id, const GBT_Command& req, const GBT_AlarmQuery& query, GBT_Alarm* alarms, int size) =0;

    /**
     * 处理查询预置位
     * @param id
     * @param req
     * @param query
     * @param presets
     * @param size
     * @return
     */
    virtual int handleQueryPreset(int id, const GBT_Command& req, const GBT_PresetQuery& query, GBT_Preset* presets, int size) =0;

    /**
     * 查询设备位置
     * @param req
     * @return true 表示允许, false 表示禁止
     */
    virtual bool handleQueryMobilePosition(int id, const GBT_Command& req, const GBT_MobilePositionQuery& query) =0;


    /**
     * 处理开关命令
     * @param id	设备序号
     * @param req	请求命令
     * @param resp	响应
     * @return true 表示已经处理
     */
    virtual bool handleSW(int id, const GBT_Command& req, const GBT_DeviceSwitch& sw) = 0;

    /**
     * 处理未定义的消息
     * @param id	设备序号
     * @param req	请求命令
     * @param resp	响应
     * @return true 表示已经处理
     */
    virtual bool handleMessage(int id, const GBT_Command& req, GBT_Command& resp) =0;


};



/**
 * DeviceAgent 监听器
 */
class GbtProxyAgentSink
{
public:
    virtual ~GbtProxyAgentSink() {}

    /**
     * 服务连接状态
     * @param status @see GBT_ONOFF
	 * @param clock  服务器时钟, UTC时间, 单位为毫秒
     */
    virtual void onConnectStatus(int status, int64_t clock) =0;

};


class GbtProxyPlaybackHandler
{
public:
    virtual ~GbtProxyPlaybackHandler() {}

    /**
    * 打开设备录像.
    * @param record    录像信息
    * @param speed     播放速度, 取值范围为: [1/8, 8], 默认为1.0.
    * @param ppStream  流
    * @return 0 表示成功, 其他表示错误码.
    */
    virtual int openPlayback(const GBT_RecordUrl& record, double speed, MStreamSource** ppStream) = 0;

    /**
    * 关闭录像流
    * @param pStream 流
    */
    virtual void closePlayback(MStreamSource* pStream) = 0;

};



/**
 * 设备代理
 */
class DLLEXPORT GbtProxyAgent
{
public:
    /**
     * 初始化
     */
    static void startup();

    /**
     * 清理
     */
    static void cleanup();

    /**
     * 获取实例
     * @return
     */
    static GbtProxyAgent& instance();

    static void setupLog();


public:
    virtual ~GbtProxyAgent() {}


    /**
     * 设置心跳间隔. 周期性发送Keepalive MESSAGE给服务.
     * @param seconds   间隔时间, 单位为秒
     * @param timeout   超时次数, 默认为3
     */
    virtual void setHeartBeat(int seconds, int timeout) =0;

    /**
     * 设置注册刷新周期, 单位为秒
     * @param seconds
     */
    virtual void setRegTime(int seconds) =0;

    /**
     * 设置RTP端口范围
     * @param minPort
     * @param maxPort
     */
    virtual void setRtpPort(uint16_t minPort, uint16_t maxPort) =0;

    /**
     * 设置UserAgent名称
     * @param name
     */
    virtual void setUserAgent(const char* name) =0;

    /**
     * 设置根设备目录信息.
     * 子设备的目录信息由 GbtMediaDevice.open 设置.
     * @param catalog
     */
    virtual void setCatalog(const GBT_Catalog& catalog) =0;

    /**
     * 设置根设备位置信息.
     * @param position
     */
    virtual void setPosition(const GBT_Position& position) =0;

    /**
     * 打开.
     * 默认启用UDP,TCP的SIP协议
     * @param ip    本机地址, 如果为空或者0.0.0.0, 内部将获取默认IP地址
     * @param port  端口
     * @param server    服务器
     * @return 0 表示成功
     */
    virtual int open(const char* ip, int port, const GBT_Server& server) =0;

    /**
     * 关闭
     */
    virtual void close() =0;

    virtual bool isOpen() =0;

    /**
     * 设置服务器. 用于动态修改服务器
     * @param server
     * @return
     */
    virtual bool setServer(const GBT_Server& server) =0;

    /**
     * 是否已经连接上服务器
     * @return
     */
    virtual bool isConnected() =0;

	virtual const char* getContact() =0;

    /**
    * 刷新注册
    * @return
    */
    virtual void refreshReg() =0;

    /**
     * 设置监听器
     * @param sink  监听器
     */
    virtual void setSink(GbtProxyAgentSink* sink) =0;


    /**
     * 创建媒体设备
     * @param id        设备ID
     * @param deviceID  设备统一编码
     * @return 设备
     */
    virtual GbtMediaDevice* createDevice(int id, const char* deviceID) =0;

    /**
     * 销毁设备
     * @param device
     */
    virtual void destroyDevice(GbtMediaDevice* device) =0;


    /**
     * 设置消息处理器
     * @param handler
     */
    virtual void setMessageHandler(GbtProxyMessageHandler* handler) =0;

    /**
     * 发出告警
     * @param alarm 告警
     * @return
     */
    virtual bool sendOutAlarm(const GBT_Alarm& alarm) =0;


    /**
     * 发送消息
     * @param deviceID  设备ID
     * @param content   内容
     * @param length    内容长度
     * @return true 表示成功
     */
    virtual bool sendMessage(const char* deviceID, const char* content, size_t length) =0;

    /**
     * 发送命令响应
     * @param deviceID  设备ID
     * @param cmdType   命令类型
     * @param sn        序列号
     * @param result    响应接口, 取值为 GBT_Status
     * @return true 表示成功
     */
    virtual bool sendResponseResult(const char* deviceID, const char* cmdType, int sn, int result) =0;


    /// HTTP 接口

    /**
     * 添加HTTP目录.
     * 用于将存储目录发布出去. 比如: addHttpDir('/var/record', "/record")
     * @param dirPath   目录路径
     * @param urlPath   URL路径, 以 '/' 开头
     * @return  true 表示成功
     */
    virtual bool addHttpDir(const char* dirPath, const char* urlPath) =0;

    /**
     * 启动HTTP服务
     * @param port  端口
     * @param webroot   静态HTML目录, 为空或者null表示当前目录下webroot子目录
     * @return  0 表示成功
     */
    virtual int startHttp(uint16_t port, const char* webroot) =0;

    /**
     * 停止HTTP服务
     */
    virtual void stopHttp() =0;


    /**
    * 设置录像回放处理器. 不设置表示不支持录像回放.
    * @param handler
    */
    virtual void setPlaybackHandler(GbtProxyPlaybackHandler* handler) = 0;

    /**
    * 结束设备的所有回放会话.
    * @param deviceID 设备ID. 为空时表示结束所以设备的回放.
    */
    virtual void closePlaybacks(const char* deviceID) =0;

    /**
    * 结束设备的所有实时会话.
    * @param deviceID 设备ID. 为空时表示结束所以设备的会话.
    */
    virtual void closePlays(const char* deviceID) =0;

    /**
     * 设置配置参数
     * @param name  参数名称, @see GbtProxyParam
     * @param value
     * @return
     */
    virtual bool setParam(GbtDeviceParam name, const char* value) =0;

    /**
    * 允许/禁止自动重新注册
    * @param enabled  允许/禁止
    * @return
    */
    virtual void enableReconnection(bool enabled) =0;

    /**
    * 设置本机地址
    * @param ip 本机地址
    * @return
    */
    virtual void setHostAddr(const char* ip) =0;

    /**
    * 指定SIP传输协议, 默认UDP传输. 在 open 之前调用
    * @param transport @see GBT_Transport
    */
    virtual void setTransport(GBT_Transport transport) = 0;

	virtual const char* findDeviceID(int id) =0;

	virtual bool findDeviceNum(const char* deviceID, int& id) =0;

};



class GbtProxyMediaDeviceDeleter
{
public:
    GbtProxyMediaDeviceDeleter()
    {
    }

    void operator () (GbtMediaDevice* device) const
    {
        GbtProxyAgent::instance().destroyDevice(device);
    }
};



} /* namespace gbt */

#endif /* GbtProxyAGENT_H_ */
